#include "app_buffer.h"
#include "log/log.h"
#include <stdlib.h>
#include <string.h>

// 初始化子缓冲区
static SubBuffer *init_sub_buffer(int total_size)
{
    // 申请子缓冲区的内存
    SubBuffer *sub_buffer = (SubBuffer *)malloc(sizeof(SubBuffer));
    // 初始化子缓冲区的属性
    sub_buffer->ptr = malloc(total_size);
    sub_buffer->total_size = total_size;
    sub_buffer->len = 0;

    return sub_buffer;
}

/**
 * 初始化
 */
Buffer *app_buffer_init(int total_size)
{
    // 申请Buffer的内存
    Buffer *buffer = (Buffer *)malloc(sizeof(Buffer));
    // 初始化buffer的属性
    buffer->sub_buffers[0] = init_sub_buffer(total_size);
    buffer->sub_buffers[1] = init_sub_buffer(total_size);
    buffer->read_index = 0;
    buffer->write_index = 1;
    // 初始化读写锁
    pthread_mutex_init(&buffer->read_lock, NULL);
    pthread_mutex_init(&buffer->write_lock, NULL);

    return buffer;
}

/**
 * 释放
 */
void app_buffer_free(Buffer *buffer)
{
    // 释放子缓冲区的ptr
    free(buffer->sub_buffers[0]->ptr);
    free(buffer->sub_buffers[1]->ptr);
    // 释放子缓冲区
    free(buffer->sub_buffers[0]);
    free(buffer->sub_buffers[1]);
    // 释放读写锁
    pthread_mutex_destroy(&buffer->read_lock);
    pthread_mutex_destroy(&buffer->write_lock);

    // 释放缓冲区
    free(buffer);
}

// 切换子缓冲区
static void swap_sub_buffer(Buffer *buffer)
{
    log_debug("准备切换子缓冲区， 加写锁");
    pthread_mutex_lock(&buffer->write_lock); // 写的过程中是不让切换的
    int temp_index = buffer->read_index;
    buffer->read_index = buffer->write_index;
    buffer->write_index = temp_index;
    log_debug("切换子缓冲区完成， 解写锁");
    pthread_mutex_unlock(&buffer->write_lock);
}

/**
 * 向缓冲区写入数据
 */
int app_buffer_write(Buffer *buffer, char *data, int data_len)
{
    // 数据的长度不能超过一个字节的大小255
    if (data_len > 255)
    {
        log_error("一次缓存的数据长度不能超过255字节");
        return -1;
    }

    log_debug("准备写入数据, 加写锁");
    pthread_mutex_lock(&buffer->write_lock);

    // 获取到写缓冲区
    SubBuffer *w_buffer = buffer->sub_buffers[buffer->write_index];

    // 要写入的数据长度加上一个字节的数据长度不能超过子缓冲区的剩余大小
    if (data_len + 1 > w_buffer->total_size - w_buffer->len)
    {
        log_error("写缓冲区剩余空间不足");
        pthread_mutex_unlock(&buffer->write_lock);
        return -1;
    }

    // 写入data数据的长度（一个字节）
    w_buffer->ptr[w_buffer->len] = data_len;  // data_len不能超过255
    // 写入data数据
    memcpy(w_buffer->ptr+w_buffer->len+1, data, data_len);
    // 更新写缓冲区的len
    w_buffer->len += data_len + 1;

    log_debug("写入数据完成， 解写锁");
    pthread_mutex_unlock(&buffer->write_lock);
    return 0;
}

/**
 * 从缓冲区读取数据
 */
int app_buffer_read(Buffer *buffer, char *data_buf, int buf_len)
{
    log_debug("准备读取数据， 加读锁");
    pthread_mutex_lock(&buffer->read_lock);

    // 获取读缓冲区
    SubBuffer *r_buffer = buffer->sub_buffers[buffer->read_index];
    // 如果读缓冲区为空，切换缓冲区
    if (r_buffer->len == 0)
    {
        swap_sub_buffer(buffer);
        // 重新获取读缓冲区
        r_buffer = buffer->sub_buffers[buffer->read_index];
        // 如果读缓冲区为空，说明缓冲区中没有数据，返回-1
        if (r_buffer->len == 0)
        {
            log_error("缓冲区中没有数据");
            pthread_mutex_unlock(&buffer->read_lock);
            return -1;
        }
        
    }

    // 先读取第一个字节，得到要读数据的长度data_len
    int data_len = r_buffer->ptr[0];
    log_debug("要读取的数据长度为%d", data_len);
    // 检查缓存容器空间是否足够
    if (data_len > buf_len)
    {
        log_error("缓存容器空间不足");
        pthread_mutex_unlock(&buffer->read_lock);
        return -1;
    }
    // 读取后面data_len个字节的数据，写入到data_buf中
    memcpy(data_buf, r_buffer->ptr+1, data_len);
    // 将后面所有未读取的数据向前移动0的位置
    memmove(r_buffer->ptr, r_buffer->ptr+data_len+1, r_buffer->len-data_len-1);
    // 更新读缓冲区的len
    r_buffer->len -= data_len + 1;

    // 如果读缓冲区为空，切换缓冲区 =》为下一次读取数据做准备
    if (r_buffer->len == 0)
    {
        swap_sub_buffer(buffer);
    }

    log_debug("读取数据完成, 解读锁");
    pthread_mutex_unlock(&buffer->read_lock);

    // 返回读取的数据长度data_len
    return data_len;
}
